﻿using System;
using System.Web.UI.WebControls;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Utilities;

using Mystery.SharePoint;

namespace Mystery.SharePoint.Layouts
{
	public partial class NewSPSite : LayoutsPageBase
	{
		Uri _webApplicationUrl = null;
		SPSite _site = null;
		SPWebApplication _webApplication = null;

		protected void Page_Load(object sender, EventArgs e)
		{
			// read and set contextual values
            _site = SPContext.Current.Site;
            _webApplication = _site.WebApplication;
            _webApplicationUrl = _webApplication.GetResponseUri(_site.Zone);

            SiteProvisioningSettings settings = _webApplication.GetSiteProvisioningSettings();
            ISiteProvisioningAuthenticationProvider provider = settings.CreateAuthenticationProvider();
            if (provider == null)
            {
                this.ToErrorPage(Resources.Page_NewSPSite_MissingAuthenticationProvider);
            }
            else
            {
                if (provider.CanProvision(_site, _site.RootWeb.CurrentUser) == false)
                {
                    this.ToAccessDeniedPage();
                }
            }

            LblWebApplicationUrl.Text = _webApplicationUrl.ToString();
            
            if (this.Page.IsPostBack == false)
            {
                AddUrlPrefixes();
                // set a default value for owner
                if (String.IsNullOrEmpty(PeOwner.CommaSeparatedAccounts) == true)
                {
                    PeOwner.CommaSeparatedAccounts = SPContext.Current.Web.CurrentUser.LoginName;
                    PeOwner.Validate();
                }
            }
            LabelURLPrefix.Text = new Uri(_webApplicationUrl, DdlUrlPrefixes.SelectedValue + "/").ToString();
		}
		
		protected void BtnCreateSite_Click(object sender, EventArgs e)
		{
            base.Validate();
            PeOwner.Validate();

            if (this.IsValid == false) return;

            string title = TxtSiteTitle.Text;
            string description = TxtSiteDescription.Text;
            string template = WebTemplatePicker.SelectedTemplate;
            uint lcid = WebTemplatePicker.Lcid;
            Uri uri = ConstructUrl();
            string owner = PeOwner.CommaSeparatedAccounts;
            string primaryAdmin;
            string secondaryAdmin;

            FindAdmins(out primaryAdmin, out secondaryAdmin, owner);

            Logger.L.AddInformation(Category.Administration, "Starting provisioning of site collection {0}", uri);

            using (SPLongOperation operation = new SPLongOperation(this.Page))
            {
                operation.LeadingHTML = string.Format(null, Resources.Page_NewSPSite_Progress_Text, uri);
                operation.Begin();

                try
                {
                    // site provisioning is done with elevated priveleges
                    // a user may be creating a site for someone else, if the code was running as the current user,
                    // the moment the site has been created, they cannot do anything else
                    SPSecurity.RunWithElevatedPrivileges(delegate
                    {
                        using (SPSite elevated = new SPSite(SPContext.Current.Site.ID))
                        {
                            using (SPSite s =
                                elevated.SelfServiceCreateSite(
                                uri.ToString(),
                                title,
                                description,
                                lcid,
                                template,
                                primaryAdmin, null, null,
                                secondaryAdmin, null, null))
                            {

                            }
                        }
                    });

                    Logger.L.AddInformation(Category.Administration, "Site collection {0} has been created");

                    // take the user to the newly created site
                    operation.End(uri.ToString());
                }
                catch (System.Threading.ThreadAbortException)
                {
                    // the operation.End() throws a ThreadAbortException, so we ignore it
                }
                catch (Exception ex)
                {
                    Logger.L.AddException(Category.Administration, ex, "Error creating site collection");

                    // present an error message to the user
                    operation.End(SPContext.Current.Web.Url + "/_layouts/Error.aspx",
                                  SPRedirectFlags.Default, Context,
                                  "ErrorText=" + Resources.Page_NewSPSite_Error +
                                  SPEncode.UrlEncode(ex.Message));
                }
            }
        }

        private void AddUrlPrefixes()
        {
            foreach (SPPrefix prefix in _webApplication.Prefixes)
            {
                if (prefix.PrefixType == SPPrefixType.WildcardInclusion)
                {
                    DdlUrlPrefixes.Items.Add(new ListItem(prefix.Name, prefix.Name));
                }
            }
        }

        private Uri ConstructUrl()
        {
            Uri url = new Uri(_webApplicationUrl, DdlUrlPrefixes.SelectedValue + "/");
            return new Uri(url, TxtSiteUrl.Text);
        }

        private void FindAdmins(out string primary, out string secondary, string owner)
        {
            string s = null;
            string p = null;
            // the specified owner always starts off as the owner of the site collection
            // when the provisioning is complete, the site collection will be changed depending
            // on what interfaces have been implemented
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                using (SPSite rootSite = SPContext.Current.Site.FindRootSPSite())
                {
                    p = owner;
                    s = (rootSite.SecondaryContact != null) ? rootSite.SecondaryContact.LoginName : null;
                }
            });
            primary = p;
            secondary = s;
        }
	}
}
